package com.zh.business.base.util;

import com.fasterxml.jackson.annotation.JsonView;
import com.zh.business.base.exception.MsgException;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;


/**
 * 
 * @Description:返回结果封装类
 * @author: Yang 
 * @date:   2017年9月30日
 */
public class JsonResult implements Serializable{

    private static final long serialVersionUID = -3296088882358820835L;

    /**
     * 正常
     */
    public static int MSG_OK = 200;

    /**
     * 错误
     */
    public static int MSG_FAIL = -1;
    /**
     * 消息
     */
    @JsonView(Object.class)
    protected String msg;
    /**
     * 状态码
     */
    @JsonView(Object.class)
    protected int code;
    /**
     * 是否成功
     */
    @JsonView(Object.class)
    protected boolean success;

    /**
     * 额外数据
     */
    @JsonView(Object.class)
    protected Object data;

    @SuppressWarnings("unchecked")
    public JsonResult(int total, Object rows) {

        data = JsonResult.kvs();
        ((HashMap<Object, Object>) data).put("rows", rows);
        ((HashMap<Object, Object>) data).put("total", total);
        this.success = true;
        this.code = MSG_OK;
        this.msg = "";
    }

    @SuppressWarnings("unchecked")
    public JsonResult(boolean hasMore, Object rows) {
        data = JsonResult.kvs();
        ((HashMap<Object, Object>) data).put("rows", rows);
        ((HashMap<Object, Object>) data).put("hasMore", hasMore);
        int total = 0;
        if (data != null && data instanceof Collection<?>) {
            total = ((Collection<?>) data).size();
        }
        ((HashMap<Object, Object>) data).put("total", total);
        this.success = true;
        this.code = MSG_OK;
        this.msg = "";
    }

    public JsonResult() {
        this.success = true;
        this.code = MSG_OK;
        this.msg = "操作成功!";
    }

    public JsonResult(String msg) {
        this.success = true;
        this.code = MSG_OK;
        this.msg = msg;
    }

    public JsonResult(boolean success, int code, String msg) {
        this.success = success;
        this.code = code;
        this.msg = msg;
    }

    public JsonResult(boolean success) {
        this.success = success;
        if (success) {
            this.code = MSG_OK;
            this.msg = "操作成功!";
        } else {
            this.code = MSG_FAIL;
            this.msg = "操作失败!";
        }

    }

    public JsonResult(boolean success, String msg) {
        this.success = success;
        if (success) {
            this.code = MSG_OK;
            this.msg = msg;
        } else {
            this.code = MSG_FAIL;
            this.msg = msg;
        }

    }

    /**
     * 返回失败结果
     *
     * @return
     */
    public static JsonResult fail() {
        return new JsonResult(false);
    }

    /**
     * 返回成功结果
     *
     * @return
     */
    public static JsonResult ok() {
        return new JsonResult(true);
    }


    /**
     * 返回成功结果,自定义提示内容
     *
     * @param msg 提示信息
     * @return
     */
    public static JsonResult ok(String msg) {
        return new JsonResult(msg);
    }

    /**
     * 返回失败结果,自定义提示内容
     *
     * @param msg 提示信息
     * @return
     */
    public static JsonResult fail(String msg) {
        return new JsonResult(false, msg);
    }

    /**
     * 返回失败结果,自定义消息类型,和提示内容
     *
     * @param code 消息类型编码
     * @param msg  提示信息
     * @return
     */
    public static JsonResult fail(int code, String msg) {
        return new JsonResult(false, code, msg);
    }

    /**
     * 返回失败结果,自定义消息类型,和额外数据
     *
     * @param data 额外数据
     * @param msg  提示信息
     * @return
     */
    public static JsonResult fail(String msg, Object data) {
        JsonResult result = new JsonResult(false, MSG_FAIL, msg);
        result.data = data;
        return result;
    }

    /**
     * 返回成功结果,自定义消息类型,和提示内容
     *
     * @param code 消息类型编码
     * @param msg  提示信息
     * @return
     */
    public static JsonResult ok(int code, String msg) {
        return new JsonResult(true, code, msg);
    }

    /**
     * 返回成功结果,自定义消息类型,和额外数据
     *
     * @param data 额外数据
     * @param msg  提示信息
     * @return
     */
    public static JsonResult ok(String msg, Object data) {
        JsonResult result = new JsonResult(true, MSG_OK, msg);
        result.data = data;
        return result;
    }

    /**
     * 返回结果,和额外数据
     *
     * @param status 是否成功
     * @param data   额外数据
     * @return
     */
    public static JsonResult data(boolean status, Object data) {
        JsonResult result = new JsonResult(status);
        result.data = data;
        return result;
    }

    /**
     * 返回前台结果
     *
     * @param status 成功或者失败
     * @return
     */
    public static JsonResult status(boolean status) {
        return new JsonResult(status);
    }

    /**
     * 返回前台结果
     *
     * @param status   成功或者失败
     * @param failCode 失败时的错误码
     * @return
     */
    public static JsonResult status(boolean status, int failCode) {
        if (status) {
            return JsonResult.ok();
        }
        JsonResult result = JsonResult.fail();
        return result.code(failCode);
    }

    /**
     * 返回前台结果
     *
     * @param status 成功或者失败
     * @param msg    失败时显示的消息
     * @return
     */
    public static JsonResult status(boolean status, String msg) {
        if (status) {
            return JsonResult.ok();
        }
        return JsonResult.fail(msg);
    }

    /**
     * 返回前台结果
     *
     * @param status   成功或者失败
     * @param msg      失败时显示的消息
     * @param failCode 失败时的错误码
     * @return
     */
    public static JsonResult status(boolean status, String msg, int failCode) {
        if (status) {
            return JsonResult.ok();
        }
        JsonResult result = JsonResult.fail(msg);
        return result.code(failCode);
    }

    /**
     * 抛出异常, 切不打印堆栈信息, 主要是让其走 error 处理接口
     *
     * @param msg
     * @return
     */
    public static JsonResult error(String msg) {
        throw new MsgException(msg);
    }

    /**
     * 抛出异常, 切不打印堆栈信息, 主要是让其走 error 处理接口
     *
     * @return
     */
    public static JsonResult error(Throwable ex) {
        try {
            throw ex;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 抛出异常, 切不打印堆栈信息, 主要是让其走 error 处理接口
     *
     * @return
     */
    public static JsonResult error() {
        throw new MsgException("操作失败");
    }

    /**
     * 添加返回数据
     *
     * @param key
     * @param value
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public JsonResult addData(String key, Object value) {
        if (this.data == null) {
            this.data = JsonResult.kvs(key, value);
        } else if (data instanceof HashMap) {
            ((HashMap) data).put(key, value);
        }

        return this;
    }

    /**
     * 生成一个HashMap<String, Object>()对象
     *
     * @return
     */
    private static HashMap<String, Object> kvs() {
        return new HashMap<String, Object>();
    }

    /**
     * 生成一个包含一个key和value的HashMap<String, Object>()对象
     *
     * @param key
     * @param value
     * @return
     */
    private static HashMap<String, Object> kvs(String key, Object value) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put(key, value);
        return map;
    }

    public Object getData() {
        return data;
    }

    public JsonResult data(Object data) {
        this.data = data;
        return this;
    }

    public JsonResult code(int code) {
        this.code = code;
        return this;
    }

    public JsonResult msg(String msg) {
        this.msg = msg;
        return this;
    }

    /**
     * @return the msg
     */
    public String getMsg() {
        return msg;
    }

    /**
     * @param msg the msg to set
     */
    public void setMsg(String msg) {
        this.msg = msg;
    }

    /**
     * @return the code
     */
    public int getCode() {
        return code;
    }

    /**
     * @param code the code to set
     */
    public void setCode(int code) {
        this.code = code;
    }

    /**
     * @return the success
     */
    public boolean isSuccess() {
        return success;
    }

    /**
     * @param success the success to set
     */
    public void setSuccess(boolean success) {
        this.success = success;
    }
}
